Skip to content

Conversation

@wmathurin
Copy link
Contributor

@wmathurin wmathurin commented Dec 4, 2025

Adding UI tests for auth flows using the new AuthFlowTester app.

The tests expect a test_config.json file which should contain:

  • the login host,
  • test users’ usernames and passwords,
  • the Connected Apps, External Client Apps and Beacon Apps configuration details.

There are a number of login tests to the various Connected Apps, External Client Apps and Beacon Apps, with web server flow or user agent flow, with and without hybrid flow, with default scopes, a subset of scopes or all scopes.
There are also a number of migration tests across apps, and also on the same app with different scopes.

For information on the org test setup see the doc "13.2 Test Org Setup for Authentication Testing".

Notes
It's not ready to merge

  • there are no multi-user tests yet
  • there are no tests that involved restarting the target app (those would be useful to avoid missing bugs that involve data that did not get persisted when expected)
  • it's not called from CI yet.

TestRun

NB: tests are actually inputing username and password in login screen
(But won't work if 2FA is required)
…to auth_ui_tests

# Conflicts:
#	native/SampleApps/AuthFlowTester/AuthFlowTester.xcodeproj/project.pbxproj
The tests expects a test_config.json with login host, consumer keys, user credentials
Tests configure the login host (if needed) then do a login / request / revoke / request / logout

We need the static boot config to be configured from the test also but we cannot bring the dev menu currently (no shake action possible from a UI test)
- default scopes, subset or all scopes
- ECA issuing JWT or not
- Web server flow or user agent flow
@github-actions
Copy link

github-actions bot commented Dec 4, 2025

1 Warning
⚠️ Big PR, try to keep changes smaller if you can.

Generated by 🚫 Danger

@wmathurin
Copy link
Contributor Author

An actual bug fix revealed by some of the tests: 8d3ab2a

@github-actions
Copy link

github-actions bot commented Dec 4, 2025

1 Warning
⚠️ Static Analysis found an issue with one or more files you modified. Please fix the issue(s).

Clang Static Analysis Issues

File Type Category Description Line Col
SFOAuthCoordinator Nullability Memory error nil assigned to a pointer which is expected to have non-null value 120 19
SFOAuthCoordinator Nullability Memory error nil assigned to a pointer which is expected to have non-null value 370 15
SFOAuthCoordinator Nullability Memory error nil assigned to a pointer which is expected to have non-null value 380 15
SFUserAccountManager Nullability Memory error Null passed to a callee that requires a non-null 2nd parameter 1570 15
SFUserAccountManager Nullability Memory error Null passed to a callee that requires a non-null 2nd parameter 1585 15
SFUserAccountManager Nullability Memory error nil passed to a callee that requires a non-null 2nd parameter 2217 13
SalesforceSDKManager Nil value used as mutex for @synchronized() (no synchronization will occur) Logic error Nil value used as mutex for @synchronized() (no synchronization will occur) 144 5
SalesforceSDKManager Nil value used as mutex for @synchronized() (no synchronization will occur) Logic error Nil value used as mutex for @synchronized() (no synchronization will occur) 156 5

Generated by 🚫 Danger

@codecov
Copy link

codecov bot commented Dec 4, 2025

Codecov Report

❌ Patch coverage is 54.38596% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.30%. Comparing base (a44dfc2) to head (33074eb).
⚠️ Report is 52 commits behind head on dev.

Files with missing lines Patch % Lines
...ore/Classes/Login/DevConfig/BootConfigEditor.swift 62.50% 15 Missing ⚠️
...SDKCore/Classes/UserAccount/SFUserAccountManager.m 11.11% 8 Missing ⚠️
...forceSDKCore/Classes/Login/SFLoginViewController.m 0.00% 2 Missing ⚠️
...forceSDKCore/Classes/Common/SalesforceSDKManager.m 0.00% 1 Missing ⚠️

❌ Your patch status has failed because the patch coverage (54.38%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #3959      +/-   ##
==========================================
+ Coverage   61.68%   63.30%   +1.62%     
==========================================
  Files         255      252       -3     
  Lines       22733    22137     -596     
==========================================
- Hits        14023    14014       -9     
+ Misses       8710     8123     -587     
Components Coverage Δ
Analytics 70.78% <ø> (ø)
Common 69.67% <ø> (-0.56%) ⬇️
Core 53.88% <55.17%> (+2.05%) ⬆️
SmartStore 74.59% <ø> (+0.59%) ⬆️
MobileSync 87.41% <ø> (ø)
Files with missing lines Coverage Δ
...lesforceSDKCore/Classes/OAuth/SFOAuthCoordinator.m 42.16% <100.00%> (+0.15%) ⬆️
...SalesforceSDKCore/Classes/OAuth/SFSDKAuthSession.m 90.62% <100.00%> (+0.30%) ⬆️
...forceSDKCore/Classes/Common/SalesforceSDKManager.m 69.56% <0.00%> (ø)
...forceSDKCore/Classes/Login/SFLoginViewController.m 10.46% <0.00%> (ø)
...SDKCore/Classes/UserAccount/SFUserAccountManager.m 36.15% <11.11%> (-0.13%) ⬇️
...ore/Classes/Login/DevConfig/BootConfigEditor.swift 52.08% <62.50%> (+0.61%) ⬆️

... and 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@wmathurin
Copy link
Contributor Author

I'm thinking of having a button that dumps all the data from the AuthFlowTester screen in an alert. It would not be very useful when manually testing but would speed up the UI tests. Collecting all the static texts on the screen takes a while.
Also we might want to speed up the inputting of login options (again a single field taking a JSON would accelerate automated tests).
@brandonpage what do you think?

…edentialsView / OAuthConfigurationView and JwtTokenView

Leveraging the new buttons in UI tests (to run faster)
@wmathurin
Copy link
Contributor Author

I'm thinking of having a button that dumps all the data from the AuthFlowTester screen in an alert. It would not be very useful when manually testing but would speed up the UI tests. Collecting all the static texts on the screen takes a while. Also we might want to speed up the inputting of login options (again a single field taking a JSON would accelerate automated tests). @brandonpage what do you think?

Done here: 3a3c10b

// Restart authentication with the updated configuration
if ([presentedViewController isKindOfClass:[SFLoginViewController class]]) {
[[SFUserAccountManager sharedInstance] restartAuthenticationForViewController:(SFLoginViewController *)presentedViewController];
[[SFUserAccountManager sharedInstance] restartAuthenticationForViewController:(SFLoginViewController *)presentedViewController recreateAuthRequest:YES];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Login options might change the consumer key / callback url / scopes so we need to restart the oauth request otherwise the new settings will not be used.

Spacer()
Image(systemName: isExpanded ? "chevron.up" : "chevron.down")
.foregroundColor(.secondary)
Button(action: {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding an import button:

  • manual tester could paste a boot config
  • UI tests make use of it - it saves on a few taps and speed up the tests a bit

[self dismissViewControllerAnimated:YES completion:^{
if ([self.delegate respondsToSelector:@selector(loginViewControllerDidReload:)]) {
[self.delegate loginViewControllerDidReload:self];
if ([self.delegate respondsToSelector:@selector(loginViewControllerDidChangeLoginOptions:)]) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reload is not enough - we need the auth request within the auth session to be recreated (see earlier comment).

AUTH040 /* RestApiTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AUTH041 /* RestApiTestView.swift */; };
AUTH042 /* OAuthConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AUTH043 /* OAuthConfigurationView.swift */; };
AUTH049 /* JwtAccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AUTH050 /* JwtAccessView.swift */; };
AUTH049 /* JwtTokenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AUTH050 /* JwtTokenView.swift */; };
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better name for the view class.

import SalesforceSDKCore

// MARK: - Labels Constants
public struct JwtTokenLabels {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pulled the labels into a struct.

  • they are used also when exporting details as JSON.
  • they are also used in UI tests.

import SalesforceSDKCore

// MARK: - Labels Constants
public struct CredentialsLabels {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pulled the labels into a struct.

  • they are used also when exporting details as JSON.
  • they are also used in UI tests.

var clientId: String
}

class AuthFlowTesterMainPageObject {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PageObject for the AuthFlowTester main screen (and also action sheets that you can bring up from the bottom tool bar).

import XCTest
import SalesforceSDKCore

class LoginPageObject {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PageObject for the login screen as well as login server action sheet and login options action sheet.

@@ -0,0 +1,87 @@
{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A file like this one is needed for the UI tests to run.
It contain a login host, app settings and user credentials.

// MARK: - Configuration Utility

/// Utility class to parse and access test configuration from command-line arguments
class TestConfigUtils {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class responsible for getting configuration from test_config.json.

@wmathurin
Copy link
Contributor Author

Tests that are missing config should fail fast
The ones involving JWT-based access token were not working:
- because there is server-side bug preventing the beacon app to be configured properly (switched to sdb38 org which runs more recent code where the issue has been resolved)
- test code was wrongly expecting beacon consumer key instead of beacon child consumer key in the JWT
… opaque token even when sfap_api scope was granted (bug filed)
… use static configuration

Always setting static configuration (so that tests can assert successfully)
…n the migration or multi users tests) => to speed things up a bit and avoid being redundant

Added some login tests that makes use of a dynamic configuration
Updated overview.md
@wmathurin wmathurin marked this pull request as ready for review December 16, 2025 05:49
@wmathurin
Copy link
Contributor Author

Not ready to merge yet.

However all the login tests are now passing locally.
Migration / multi users tests are still struggling though.

Expecting more users in test_config.json
Using different users in different test suites
@github-actions
Copy link

github-actions bot commented Dec 17, 2025

TestsPassed ☑️SkippedFailed ❌️
SalesforceSDKCore iOS ^26 Test Results585 ran577 ✅8 ❌
TestResult
SalesforceSDKCore iOS ^26 Test Results
DomainDiscoveryCoordinatorTests.testExtraQueryParameters()❌ failure
SFUserAccountManagerTests.testAuthHandler❌ failure
SFUserAccountManagerTests.testLoginViewControllerCustomizations❌ failure
SalesforceRestAPITests.testCollectionUpdate❌ failure
SalesforceRestAPITests.testCreateQuerySearchDelete❌ failure
SalesforceRestAPITests.testUpdateWithIfUnmodifiedSince❌ failure
SalesforceRestAPITests.testUploadOwnedFilesDelete❌ failure
SalesforceRestAPITests.testUploadShareFileSharesSharedFilesUnshareDelete❌ failure

@github-actions
Copy link

github-actions bot commented Dec 17, 2025

TestsPassed ☑️SkippedFailed ❌️
SalesforceSDKCore iOS ^18 Test Results586 ran582 ✅4 ❌
TestResult
SalesforceSDKCore iOS ^18 Test Results
DevInfoViewControllerTests.testDevInfoViewRendersRealWorldData()❌ failure
SFUserAccountManagerTests.testUserAccountEncoding❌ failure
SalesforceRestAPITests.testCreateQuerySearchDelete❌ failure
SalesforceRestAPITests.testUploadShareFileSharesSharedFilesUnshareDelete❌ failure

Copy link
Contributor

@brandonpage brandonpage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! There are an impressive amount of login scenarios covered here (and I have a lot of work to do to match).

I am a little surprised how how many SDK updates were necessary to apply the consumer key and redirect URI. Perhaps a MVVM overhaul like we did on Android could be helpful for organization in the future.

At some point I will steal your PageObject improvements and add them to the UITest repo so we can consumer them from there someday.

dynamicScopes: String,
useWebServerFlow: Bool,
useHybridFlow: Bool,
supportWelcomeDiscovery: Bool,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love the use of trailing commas, I didn't know that was in Swift .

Getting a 403 when invoking the single access bridge API with a beacon app access token (file a bug with auth team).
@wmathurin wmathurin merged commit e8a07ac into forcedotcom:dev Dec 18, 2025
21 of 27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants